home *** CD-ROM | disk | FTP | other *** search
/ Precision Software Appli…tions Silver Collection 1 / Precision Software Applications Silver Collection Volume One (PSM) (1993).iso / windows / games / wincapt.arj / PRINT.C < prev    next >
C/C++ Source or Header  |  1992-07-14  |  25KB  |  735 lines

  1. //********************************************************************
  2. //
  3. //  print.c
  4. //
  5. //  Source file for Device-Independent Bitmap (DIB) API.  Provides
  6. //  the following functions:
  7. //
  8. //  PrintWindow()       - Prints all or part of a window
  9. //  PrintScreen()       - Prints the entire screen
  10. //  PrintDIB()          - Prints the specified DIB
  11. //
  12. // Development Team: Mark Bader
  13. //                   Patrick Schreiber
  14. //                   Garrett McAuliffe
  15. //                   Eric Flo
  16. //                   Tony Claflin
  17. //                   Dan Ruder
  18. //
  19. // Written by Microsoft Product Support Services, Developer Support.
  20. // Copyright (c) 1991 Microsoft Corporation. All rights reserved.
  21. //********************************************************************
  22.  
  23. #include <windows.h>
  24. #include <string.h>
  25. #include "dibdll.h"     // Header for printing dialog & DLL instance handle
  26. #include "dibapi.h"     // Header for DIB functions
  27. #include "dibutil.h"    // Auxiliary functions
  28.  
  29.  
  30. extern HANDLE ghDLLInst;     // Global handle to DLL's instance
  31.  
  32. /***************************************************************
  33.  * Typedefs
  34.  **************************************************************/
  35.  
  36. /* Structure used for Banding */
  37.  
  38. typedef struct
  39. {
  40.    BOOL bGraphics;
  41.    BOOL bText;
  42.    RECT GraphicsRect;
  43. } BANDINFOSTRUCT;
  44.  
  45.  
  46. /****************************************************************
  47.  * Variables
  48.  ***************************************************************/
  49.  
  50. HWND hDlgAbort;                    // Handle to Abort Dialog
  51. char szPrintDlg[] = "Printing";    // Name of Print dialog from .RC
  52. BOOL bAbort = FALSE;               // Abort a print operation?
  53. char gszDevice[50];                // Keeps track out device (e.g. "HP LaserJet")
  54. char gszOutput[50];                // Output device (e.g. "LPT1:")
  55.  
  56. /***************************************************************
  57.  * Function prototypes for functions local to this module
  58.  **************************************************************/
  59.  
  60.  
  61. BOOL FAR PASCAL PrintAbortProc(HDC, short);
  62. int FAR PASCAL PrintAbortDlg(HWND, unsigned, WORD, LONG);
  63. WORD PrintBand(HDC, LPRECT, LPRECT, BOOL, BOOL, LPBITMAPINFOHEADER, LPSTR);
  64. HDC GetPrinterDC(void);
  65. void CalculatePrintRect(HDC, LPRECT, WORD, DWORD, DWORD);
  66.  
  67.  
  68. /**********************************************************************
  69.  *
  70.  * PrintWindow()
  71.  *
  72.  *
  73.  * Description:
  74.  *
  75.  * This function prints the specified window on the default
  76.  * printer.
  77.  *
  78.  * Parameters:
  79.  *
  80.  * HWND hWnd       - Specifies the window to print.  The window must
  81.  *                   not be iconic and must be topmost on the display.
  82.  *
  83.  * WORD fPrintArea - Specifies the area of the window to print.  Must be
  84.  *                   one of PW_ALL, PW_CLIENT, PW_CAPTION,  or PW_MENUBAR
  85.  *
  86.  * WORD fPrintOpt  - Print options (one of PW_BESTFIT, PW_STRETCHTOPAGE, or
  87.  *                   PW_SCALE)
  88.  *
  89.  * WORD wXScale, wYScale - X and Y scaling factors if PW_SCALE is specified
  90.  *
  91.  * LPSTR szJobName - Name that you would like to give to this print job (this
  92.  *                   name shows up in the Print Manager as well as the
  93.  *                   "Now Printing..." dialog box).
  94.  * Return Value:
  95.  *      ERR_DIBFUNCTION or any return value from PrintDIB
  96.  *
  97.  * History:   
  98.  * 
  99.  *     Date      Author       Reason         
  100.  *     9/15/91   Mark Bader   Created         
  101.  *
  102.  **********************************************************************/
  103.  
  104.  
  105. WORD FAR PrintWindow(HWND hWnd,         // Window to be printed
  106.                  WORD fPrintArea,   // Area of window to be printed
  107.                  WORD fPrintOpt,    // Print options
  108.                  WORD wXScale,      // X Scaling factor if PW_SCALE is used
  109.                  WORD wYScale,      // Y Scaling factor if PW_SCALE is used
  110.                  LPSTR szJobName)   // Name of print job
  111. {
  112.    HDIB hDib;          // Handle to the DIB
  113.    WORD wReturn;       // our return value
  114.  
  115.    /*
  116.     * Parameter validation
  117.     */
  118.    if (!hWnd)
  119.       return (ERR_INVALIDHANDLE);  // Invalid Window
  120.  
  121.    /*
  122.     * Copy the Window to a DIB and print it.
  123.     */
  124.    hDib = CopyWindowToDIB(hWnd, fPrintArea);
  125.    if (!hDib)
  126.       return (ERR_DIBFUNCTION); // CopyWindowToDIB failed!
  127.    wReturn = PrintDIB(hDib, fPrintOpt, wXScale, wYScale, szJobName);
  128.  
  129.    /*
  130.     * Call DestroyDIB to free the memory the dib takes up.
  131.     */
  132.    DestroyDIB(hDib);
  133.    return wReturn;   // return the value from PrintDIB
  134. }
  135.  
  136.  
  137.  
  138. /**********************************************************************
  139.  *
  140.  * PrintScreen()
  141.  *
  142.  *
  143.  * Description:
  144.  *
  145.  * This function prints the specified portion of the display screen on the
  146.  * default printer using the print options specified.  The print
  147.  * options are listed in dibapi.h.
  148.  *
  149.  * Parameters:
  150.  *
  151.  * LPRECT rRegion  - Specifies the region of the screen (in screen
  152.  *                   coordinates) to print
  153.  *
  154.  * WORD fPrintOpt  - Print options  (PW_BESTFIT, PW_STRETCHTOPAGE, or PW_SCALE)
  155.  *
  156.  * WORD wXScale, wYScale - X and Y scaling factors if PW_SCALE is specified
  157.  *
  158.  * LPSTR szJobName - Name that you would like to give to this print job (this
  159.  *                   name shows up in the Print Manager as well as the
  160.  *                   "Now Printing..." dialog box).
  161.  *
  162.  * Return Value:
  163.  *      ERR_DIBFUNCTION or any return value from PrintDIB
  164.  *
  165.  * History:   
  166.  * 
  167.  *     Date      Author       Reason         
  168.  *     9/15/91   Mark Bader   Created         
  169.  *
  170.  **********************************************************************/
  171.  
  172.  
  173. WORD FAR PrintScreen(LPRECT rRegion,    // Region to print (in screen coords)
  174.                  WORD fPrintOpt,    // print options
  175.                  WORD wXScale,      // X scaling (used if PW_SCALE specified)
  176.                  WORD wYScale,      // Y scaling (used if PW_SCALE specified)
  177.                  LPSTR szJobName)   // Name of print job
  178. {
  179.    HDIB hDib;          // A Handle to our DIB
  180.    WORD wReturn;       // Return value
  181.  
  182.    /*
  183.     * Copy the screen contained in the specified rectangle to a DIB
  184.     */
  185.    hDib = CopyScreenToDIB(rRegion);
  186.    if (!hDib)
  187.       return (ERR_DIBFUNCTION);   // CopyScreenToDIB failed!
  188.    wReturn = PrintDIB(hDib, fPrintOpt, wXScale, wYScale, szJobName);
  189.    DestroyDIB(hDib);
  190.    return wReturn; // Return the value that PrintDIB returned
  191. }
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198. /**********************************************************************
  199.  *
  200.  * PrintDIB()
  201.  *
  202.  * Description:
  203.  *
  204.  * This routine prints the specified DIB.  The actual printing is done
  205.  * in the PrintBand() routine (see below), this procedure drives the
  206.  * printing operation.  PrintDIB() has the code to handle both banding
  207.  * and non-banding printers.  A banding printer can be distinguished by
  208.  * the GetDeviceCaps() API (see the code below).  On banding devices,
  209.  * must repeatedly call the NEXTBAND escape to get the next banding
  210.  * rectangle to print into.  If the device supports the BANDINFO escape,
  211.  * it should be used to determine whether the band "wants" text or
  212.  * graphics (or both).  On non-banding devices, we can ignore all this
  213.  * and call PrintBand() on the entire page.
  214.  *
  215.  * Parameters:
  216.  *
  217.  * HDIB hDib       - Handle to dib to be printed
  218.  *
  219.  * WORD fPrintOpt  - tells which print option to use (PW_BESTFIT,
  220.  *                   PW_STRETCHTOPAGE, OR PW_SCALE)
  221.  *
  222.  * WORD wXScale, wYScale - X and Y scaling factors (integers) for
  223.  *                   printed output if the PW_SCALE option is used.
  224.  *
  225.  * LPSTR szJobName - Name that you would like to give to this print job (this
  226.  *                   name shows up in the Print Manager as well as the
  227.  *                   "Now Printing..." dialog box).
  228.  *
  229.  * Return Value:  (see errors.h for description)
  230.  *
  231.  * One of: ERR_INVALIDHANDLE
  232.  *         ERR_LOCK
  233.  *         ERR_SETABORTPROC
  234.  *         ERR_STARTDOC
  235.  *         ERR_NEWFRAME
  236.  *         ERR_ENDDOC
  237.  *         ERR_GETDC
  238.  *         ERR_STRETCHDIBITS
  239.  *
  240.  * History:   
  241.  * 
  242.  *     Date      Author       Reason         
  243.  *     9/15/91   Mark Bader   Created, based on DIBVIEW's DibPrint()
  244.  *
  245.  ********************************************************************/
  246.  
  247.  
  248. WORD FAR PrintDIB(HDIB hDib,        // Handle to the DIB
  249.               WORD fPrintOpt,   // Print Options
  250.               WORD wXScale,     // X Scaling factor
  251.               WORD wYScale,     // Y Scaling factor
  252.               LPSTR szJobName)  // Name of print job
  253. {
  254.    HDC hPrnDC;                  // DC to the printer
  255.    RECT rect;                   // Rect structure used for banding
  256.    BANDINFOSTRUCT biBandInfo;   // Used for banding
  257.    int nTemp;                   // Temp number used to check banding capability
  258.    LPSTR lpBits;                // pointer to the DIB bits
  259.    LPBITMAPINFOHEADER lpDIBHdr; // Pointer to DIB header
  260.    int nBandCount = 0;          // used for print dialog box to count bands
  261.    WORD wErrorCode = 0;         // Error code to return
  262.    RECT rPrintRect;             // Rect which specifies the area on the printer
  263.                                 // (in printer coordinates) which we
  264.                                 // want the DIB to go to
  265.    char szBuffer[70];           // Buffer to hold message for "Printing" dlg box
  266.    char szJobNameTrunc[35];     // szJobName truncated to 31 characters, since
  267.                                 // STARTDOC can't accept a string longer than 31
  268.  
  269.    /*
  270.     * Paramter validation
  271.     */
  272.    if (!hDib)
  273.       return (ERR_INVALIDHANDLE);
  274.  
  275.    /*
  276.     * Get pointer to DIB header
  277.     */
  278.    lpDIBHdr = (LPBITMAPINFOHEADER)GlobalLock(hDib);
  279.    if (!lpDIBHdr) // Check that we have a valid pointer
  280.       return (ERR_LOCK);
  281.    lpBits = FindDIBBits((LPSTR)lpDIBHdr); // Find pointer to DIB bits
  282.    if (hPrnDC = GetPrinterDC())
  283.    {
  284.       SetStretchBltMode(hPrnDC, COLORONCOLOR);
  285.  
  286.       /*
  287.        * Determine rPrintRect (printer area to print to) from the
  288.        * fPrintOpt.  Fill in rPrintRect.left and .top from wXScale and
  289.        * wYScale just in case we use PW_SCALE (see the function
  290.        * CalculatePrintRect).
  291.        */
  292.       rPrintRect.left = wXScale;
  293.       rPrintRect.top = wYScale;
  294.       CalculatePrintRect(hPrnDC, &rPrintRect, fPrintOpt, lpDIBHdr->biWidth,
  295.                          lpDIBHdr->biHeight);
  296.  
  297.       /*
  298.        * Initialize the abort procedure.
  299.        */
  300.       hDlgAbort = CreateDialog(ghDLLInst, szPrintDlg, GetFocus(), PrintAbortDlg);
  301.  
  302.       /*
  303.        * Set the text inside the dialog to the name of our print job
  304.        */
  305.       lstrcpy(szJobNameTrunc, szJobName);
  306.       szJobNameTrunc[31] = '\0';           // Truncate string to 31 chars
  307.       wsprintf(szBuffer, "Printing '%s'", (LPSTR)szJobNameTrunc);
  308.       SetDlgItemText(hDlgAbort, IDC_PRINTTEXT1, (LPSTR)szBuffer);
  309.  
  310.       /*
  311.        * Set global variable bAbort to FALSE.  This will get set to TRUE
  312.        * in our PrintAbortDlg() procedure if the user selects the
  313.        * CANCEL button in our dialog box
  314.        */
  315.       bAbort = FALSE;
  316.  
  317.       /*
  318.        * Call the Escape() which will set up the Abort Procedure
  319.        */
  320.       if (Escape(hPrnDC, SETABORTPROC, NULL, (LPSTR)PrintAbortProc, NULL
  321.                  ) < 0)
  322.          return (ERR_SETABORTPROC);
  323.  
  324.       /*
  325.        * Call Escape() with STARTDOC -- starts print job
  326.        */
  327.       if (Escape(hPrnDC, STARTDOC, lstrlen((LPSTR)szJobNameTrunc), (LPSTR)
  328.                  szJobNameTrunc, NULL) < 0)
  329.       {
  330.  
  331.          // Oops, something happened, let's clean up here and return
  332.          DestroyWindow(hDlgAbort);   // Remove abort dialog box
  333.          DeleteDC(hPrnDC);
  334.          GlobalUnlock(hDib);
  335.          return (ERR_STARTDOC);
  336.       }
  337.  
  338.       /*
  339.        * Fill in initial values for our BandInfo Structure to
  340.        * tell driver we can want to do graphics and text, and
  341.        * also which area we want the graphics to go in.
  342.        */
  343.       biBandInfo.bGraphics = TRUE;
  344.       biBandInfo.bText = TRUE;
  345.       biBandInfo.GraphicsRect = rPrintRect;
  346.  
  347.       /*
  348.        * Check if need to do banding.  If we do, loop through
  349.        *  each band in the page, calling NEXTBAND and BANDINFO
  350.        *  (if supported) calling PrintBand() on the band.  Else,
  351.        *  call PrintBand() with the entire page as our clipping
  352.        *  rectangle!
  353.        */
  354.       nTemp = NEXTBAND;
  355.       if (Escape(hPrnDC, QUERYESCSUPPORT, sizeof(int), (LPSTR)&nTemp, NULL))
  356.       {
  357.          BOOL bBandInfoDevice;
  358.  
  359.          /*
  360.           * Check if device supports the BANDINFO escape.
  361.           */
  362.  
  363.          nTemp = BANDINFO;
  364.          bBandInfoDevice = Escape(hPrnDC, QUERYESCSUPPORT, sizeof(int), (LPSTR
  365.                                   )&nTemp, NULL);
  366.  
  367.          /*
  368.           * Do each band -- Call Escape() with NEXTBAND, then the
  369.           * rect structure returned is the area where we are to
  370.           * print in.  This loop exits when the rect area is empty.
  371.           */
  372.          while (Escape(hPrnDC, NEXTBAND, NULL, NULL, (LPSTR)&rect) && !
  373.                 IsRectEmpty(&rect))
  374.          {
  375.             char szTmpBuf[100];
  376.  
  377.             /*
  378.              * Do the BANDINFO, if needed.
  379.              */
  380.  
  381.             if (bBandInfoDevice)
  382.                Escape(hPrnDC, BANDINFO, sizeof(BANDINFOSTRUCT), (LPSTR)&
  383.                       biBandInfo, (LPSTR)&biBandInfo);
  384.             wsprintf(szTmpBuf, "Printing Band Number %d", ++nBandCount);
  385.             SetDlgItemText(hDlgAbort, IDC_PERCENTAGE, (LPSTR)szTmpBuf);
  386.  
  387.             /*
  388.              * Call PrintBand() to do actual output into band.
  389.              *  Pass in our band-info flags to tell what sort
  390.              *  of data to output into the band.  Note that on
  391.              *  non-banding devices, we pass in the default bandinfo
  392.              *  stuff set above (i.e. bText=TRUE, bGraphics=TRUE).
  393.              */
  394.             wErrorCode = PrintBand(hPrnDC, &rPrintRect, &rect,
  395.                                    biBandInfo.bText, biBandInfo.bGraphics,
  396.                                    lpDIBHdr, lpBits);
  397.          }
  398.       }
  399.       else
  400.       {
  401.  
  402.          /*
  403.           * Print the whole page -- non-banding device.
  404.           */
  405.          rect = rPrintRect;
  406.          SetDlgItemText(hDlgAbort, IDC_PERCENTAGE, (LPSTR)
  407.                         "Sending bitmap to printer...");
  408.          wErrorCode = PrintBand(hPrnDC, &rPrintRect, &rect, TRUE, TRUE,
  409.                                 lpDIBHdr, lpBits);
  410.  
  411.          /*
  412.           * Non-banding devices need a NEWFRAME
  413.           */
  414.          if (Escape(hPrnDC, NEWFRAME, NULL, NULL, NULL) < 0)
  415.             return (ERR_NEWFRAME);
  416.       }
  417.  
  418.       /*
  419.        * End the print operation.  Only send the ENDDOC if
  420.        *   we didn't abort or error.
  421.        */
  422.       if (!bAbort)
  423.       {
  424.          if (Escape(hPrnDC, ENDDOC, NULL, NULL, NULL) < 0)
  425.          {
  426.             /*
  427.              * We errored out on ENDDOC, but don't return here - we still
  428.              * need to close the dialog box, free proc instances, etc.
  429.              */
  430.             wErrorCode = ERR_ENDDOC;
  431.          }
  432.          DestroyWindow(hDlgAbort);
  433.       }
  434.  
  435.  
  436.       /*
  437.        * All done, clean up.
  438.        */
  439.       DeleteDC(hPrnDC);
  440.    }
  441.    else
  442.       wErrorCode = ERR_GETDC;   // Couldn't get Printer DC!
  443.    GlobalUnlock(hDib);
  444.    return (wErrorCode);
  445. }
  446.  
  447.  
  448.  
  449.  
  450. // *******************************************************************
  451. // Auxiliary Functions
  452. //     -- Local to this module only
  453. // *******************************************************************
  454.  
  455.  
  456. /*********************************************************************
  457.  *
  458.  * CalculatePrintRect()
  459.  *
  460.  * Given fPrintOpt and a size of the DIB, return the area on the
  461.  * printer where the image should go (in printer coordinates).  If
  462.  * fPrintOpt is PW_SCALE, then lpPrintRect.left and .top should
  463.  * contain WORDs which specify the scaling factor for the X and
  464.  * Y directions, respecively.
  465.  *
  466.  * History:   
  467.  * 
  468.  *     Date      Author       Reason         
  469.  *     9/15/91   Mark Bader   Created based on DIBVIEW
  470.  *
  471.  ********************************************************************/
  472.  
  473.  
  474. void CalculatePrintRect(HDC hDC,             // HDC to printer DC
  475.                         LPRECT lpPrintRect,  // Returned PrintRect
  476.                         WORD fPrintOpt,      // Options
  477.                         DWORD cxDIB,         // Size of DIB - x
  478.                         DWORD cyDIB)         // Size of DIB - y
  479. {
  480.    int cxPage, cyPage, cxInch, cyInch;
  481.  
  482.    if (!hDC)
  483.       return;
  484.  
  485.    /*
  486.     * Get some info from printer driver
  487.     */
  488.    cxPage = GetDeviceCaps(hDC, HORZRES);     // Width of printr page - pixels
  489.    cyPage = GetDeviceCaps(hDC, VERTRES);     // Height of printr page - pixels
  490.    cxInch = GetDeviceCaps(hDC, LOGPIXELSX);  // Printer pixels per inch - X
  491.    cyInch = GetDeviceCaps(hDC, LOGPIXELSY);  // Printer pixels per inch - Y
  492.    switch (fPrintOpt)
  493.       {
  494.  
  495.    /*
  496.     * Best Fit case -- create a rectangle which preserves
  497.     * the DIB's aspect ratio, and fills the page horizontally.
  498.     *
  499.     * The formula in the "->bottom" field below calculates the Y
  500.     * position of the printed bitmap, based on the size of the
  501.     * bitmap, the width of the page, and the relative size of
  502.     * a printed pixel (cyInch / cxInch).
  503.     */
  504.    case PW_BESTFIT:
  505.       lpPrintRect->top = 0;
  506.       lpPrintRect->left = 0;
  507.       lpPrintRect->bottom = (int)(((double)cyDIB * cxPage * cyInch) / ((double
  508.                             )cxDIB * cxInch));
  509.       lpPrintRect->right = cxPage;
  510.       break;
  511.  
  512.    /*
  513.     * Scaling option -- lpPrintRect's top/left contain
  514.     * multipliers to multiply the DIB's height/width by.
  515.     */
  516.  
  517.    case PW_SCALE:
  518.    {
  519.       int cxMult, cyMult;
  520.  
  521.       cxMult = lpPrintRect->left;
  522.       cyMult = lpPrintRect->top;
  523.       lpPrintRect->top = 0;
  524.       lpPrintRect->left = 0;
  525.       lpPrintRect->bottom = (int)(cyDIB * cyMult);
  526.       lpPrintRect->right = (int)(cxDIB * cxMult);
  527.    }
  528.       break;
  529.  
  530.    /*
  531.     * Stretch To Page case -- create a rectangle
  532.     * which covers the entire printing page (note that this
  533.     * is also the default).
  534.     */
  535.    case PW_STRETCHTOPAGE:
  536.    default:
  537.       lpPrintRect->top = 0;
  538.       lpPrintRect->left = 0;
  539.       lpPrintRect->bottom = cyPage;
  540.       lpPrintRect->right = cxPage;
  541.       break;
  542.       }
  543. }
  544.  
  545.  
  546.  
  547. /*********************************************************************
  548.  *
  549.  * PrintBand()
  550.  *
  551.  * This routine does ALL output to the printer.  It is called from
  552.  * the PrintDIB() routine.  It is called for both banding and non-
  553.  * banding printing devices.  lpRectClip contains the rectangular
  554.  * area we should do our output into (i.e. we should clip our output
  555.  * to this area).  The flags fDoText and fDoGraphics should be set
  556.  * appropriately (if we want any text output to the rectangle, set
  557.  * fDoText to true).  Normally these flags are returned on banding
  558.  * devices which support the BANDINFO escape.
  559.  *
  560.  * History:   
  561.  * 
  562.  *     Date      Author       Reason         
  563.  *     9/15/91   Mark Bader   Created based on DIBVIEW
  564.  *
  565.  ********************************************************************/
  566.  
  567.  
  568. WORD PrintBand(HDC hDC,           // Handle to the Printer DC
  569.                LPRECT lpRectOut,  // Rect where entire DIB is to go
  570.                LPRECT lpRectClip, // Clippping rect where this portion goes
  571.                BOOL fDoText,      // TRUE if this band is for text
  572.                BOOL fDoGraphics,  // TRUE if this band is for graphics
  573.                LPBITMAPINFOHEADER lpDIBHdr,   // Pointer to DIB header
  574.                LPSTR lpDIBBits)   // Pointer to DIB bits
  575. {
  576.    RECT rect;                   // Temporary rectangle
  577.    double dblXScaling,          // X and Y scaling factors
  578.           dblYScaling;
  579.    WORD wReturn = 0;            // Return code
  580.  
  581.    if (fDoGraphics)
  582.    {
  583.       dblXScaling = ((double)lpRectOut->right - lpRectOut->left) / (double)
  584.                     lpDIBHdr->biWidth;
  585.       dblYScaling = ((double)lpRectOut->bottom - lpRectOut->top) / (double)
  586.                     lpDIBHdr->biHeight;
  587.       /*
  588.        * Now we set up a temporary rectangle -- this rectangle
  589.        *  holds the coordinates on the paper where our bitmap
  590.        *  WILL be output.  We can intersect this rectangle with
  591.        *  the lpClipRect to see what we NEED to output to this
  592.        *  band.  Then, we determine the coordinates in the DIB
  593.        *  to which this rectangle corresponds (using dbl?Scaling).
  594.        */
  595.       IntersectRect(&rect, lpRectOut, lpRectClip);
  596.       if (!IsRectEmpty(&rect))
  597.       {
  598.          RECT rectIn;
  599.  
  600.          rectIn.left = (int)((rect.left - lpRectOut->left) / dblXScaling + 0.5
  601.                        );
  602.          rectIn.top = (int)((rect.top - lpRectOut->top) / dblYScaling + 0.5);
  603.          rectIn.right = (int)(rectIn.left + (rect.right - rect.left) /
  604.                         dblXScaling + 0.5);
  605.          rectIn.bottom = (int)(rectIn.top + (rect.bottom - rect.top) /
  606.                          dblYScaling + 0.5);
  607.          if (!StretchDIBits(hDC,                              // DestDC
  608.                             rect.left,                        // DestX
  609.                             rect.top,                         // DestY
  610.                             rect.right - rect.left,           // DestWidth
  611.                             rect.bottom - rect.top,           // DestHeight
  612.                             rectIn.left,                      // SrcX
  613.                             (int)(lpDIBHdr->biHeight) -       // SrcY
  614.                             rectIn.top - (rectIn.bottom - rectIn.top),
  615.                             rectIn.right - rectIn.left,       // SrcWidth
  616.                             rectIn.bottom - rectIn.top,       // SrcHeight
  617.                             lpDIBBits,                        // lpBits
  618.                             (LPBITMAPINFO)lpDIBHdr,           // lpBitInfo
  619.                             DIB_RGB_COLORS,                   // wUsage
  620.                             SRCCOPY))                         // dwROP
  621.             wReturn = ERR_STRETCHDIBITS; // StretchDIBits() failed!
  622.       }
  623.    }
  624.    return wReturn;
  625. }
  626.  
  627.  
  628. /***********************************************************************
  629.  *
  630.  * GetPrinterDC()
  631.  *
  632.  * Return a DC to the currently selected printer.
  633.  * Returns NULL on error.
  634.  *
  635.  * History:   
  636.  * 
  637.  *     Date      Author       Reason         
  638.  *     9/15/91   Mark Bader   Created based on DIBVIEW
  639.  *
  640.  ***********************************************************************/
  641.  
  642.  
  643. HDC GetPrinterDC(void)
  644. {
  645.    static char szPrinter[64];
  646.    char *szDevice, *szDriver, *szOutput;
  647.  
  648.    GetProfileString("windows", "device", "", szPrinter, 64);
  649.    if ((szDevice = strtok(szPrinter, ",")) && (szDriver = strtok(NULL, ", "))
  650.        && (szOutput = strtok(NULL, ", ")))
  651.    {
  652.       lstrcpy((LPSTR)gszDevice, (LPSTR)szDevice);    // Copy to global variables
  653.       lstrcpy((LPSTR)gszOutput, (LPSTR)szOutput);
  654.       return CreateDC(szDriver, szDevice, szOutput, NULL);
  655.    }
  656.    return NULL;
  657. }
  658.  
  659.  
  660. /**********************************************************************
  661.  * PrintAbortProc()
  662.  *
  663.  * Abort procedure - contains the message loop while printing is
  664.  * in progress.  By using a PeekMessage() loop, multitasking
  665.  * can occur during printing.
  666.  *
  667.  * History:   
  668.  * 
  669.  *     Date      Author       Reason         
  670.  *     9/15/91   Mark Bader   Created         
  671.  *
  672.  **********************************************************************/
  673.  
  674.  
  675. BOOL FAR PASCAL PrintAbortProc(HDC hDC, short code)
  676. {
  677.    MSG msg;
  678.  
  679.    while (!bAbort && PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  680.       if (!IsDialogMessage(hDlgAbort, &msg))
  681.       {
  682.          TranslateMessage(&msg);
  683.          DispatchMessage(&msg);
  684.       }
  685.    return (!bAbort);
  686. }
  687.  
  688. /***********************************************************************
  689.  *
  690.  * PrintAbortDlg()
  691.  *
  692.  *
  693.  * This is the Dialog Procedure which will handle the "Now Printing"
  694.  * dialog box.  When the user presses the "Cancel" button, the
  695.  * global variable bAbort is set to TRUE, which causes the
  696.  * PrintAbortProc to exit, which in turn causes the printing
  697.  * operation to terminate.
  698.  *
  699.  * History:   
  700.  * 
  701.  *     Date      Author       Reason         
  702.  *     9/15/91   Mark Bader   Created         
  703.  *
  704.  ***********************************************************************/
  705.  
  706.  
  707. int FAR PASCAL PrintAbortDlg(HWND hWnd,   /* Handle to dialog box */ unsigned
  708.                              msg, /* Message */ WORD wParam, LONG lParam)
  709. {
  710.    switch (msg)
  711.       {
  712.    case WM_INITDIALOG:
  713.    {
  714.       char szBuffer[100];
  715.  
  716.       /*
  717.        * Fill in the text which specifies where this bitmap
  718.        * is going ("on HP LaserJet on LPT1", for example)
  719.        */
  720.  
  721.       wsprintf(szBuffer, "on %s on %s", (LPSTR)gszDevice, (LPSTR)gszOutput);
  722.       SetDlgItemText(hWnd, IDC_PRINTTEXT2, (LPSTR)szBuffer);
  723.       SetFocus(GetDlgItem(hWnd, IDCANCEL));
  724.    }
  725.       return TRUE;     // Return TRUE because we called SetFocus()
  726.  
  727.    case WM_COMMAND:
  728.       bAbort = TRUE;
  729.       DestroyWindow(hWnd);
  730.       return TRUE;
  731.       break;
  732.       }
  733.    return FALSE;
  734. }
  735.